#!/usr/bin/python
# coding=utf-8
import win32api
import win32con
import sys


# 变量名对齐函数
def def_align(str_def, max_len):
    name_len = len(str_def)
    if name_len > max_len:
        win32api.MessageBox(0, "名字过长，最大限制为%d字符" % max_len, "提醒", win32con.MB_OK)
        exit(0)
    space_num = max_len - name_len + 1  # 至少加一个空格
    if space_num > 0:  # 用空格补齐len个字符长度
        i = 0
        while i < space_num:
            str_def += " "
            i += 1
    return str_def

# 行处理函数
def line_split(line):
    list1 = line.split('#')      # 分离注释
    list2 = list1[0].split('=')  # 分离默认值
    name = list2[0].replace('\n', '')  # 去掉换行符
    name = name.replace(' ', '')   # 去掉空格
    value = ''
    if len(list2) > 1:  # 有默认值
        value = list2[1].replace(' ', '')
    comment = ""
    if len(list1) > 1:
        comment += "   //" + list1[1].replace('\n', '')
    return name, value, comment


# 程序开始
obj_path = sys.argv[1]
# 打开register.h
fpwh = open(obj_path + "\\registers.h", 'w')
# 清空
fpwh.truncate()
# 写入注释头
fpwh.write("\
/*---------------------------------------------------------------------\n\
 * File name: registers.h\n\
 *\n\
 * Copyright (c) <2020-2022>, <ChenLong>\n\
 *\n\
 * All rights reserved.\n\
 *\n\
 * Author: ChenLong\n\
 * Email: worldlong@foxmail.com\n\
 *--------------------------------------------------------------------*/\n")
fpwh.write("#pragma once\n")
fpwh.write("#include <stdint.h>\n")
fpwh.write("/*\n\
All registers are 16 bits\n\
*/\n")
# 打开register.cpp
fpwc = open(obj_path + "\\registers.cpp", 'w')
# 清空
fpwc.truncate()
# 写入注释头
fpwc.write("\
/*---------------------------------------------------------------------\n\
 * File name: registers.cpp\n\
 *\n\
 * Copyright (c) <2020-2022>, <ChenLong>\n\
 *\n\
 * All rights reserved.\n\
 *\n\
 * Author: ChenLong\n\
 * Email: worldlong@foxmail.com\n\
 *--------------------------------------------------------------------*/\n")
fpwc.write("#include \"registers.h\"\n")
fpwc.write("/*\n*/\n")
fpwc.write("__no_init uint16_t reg_table[REG_NUMBER];\n")
fpwc.write("/*\n*/\n")
fpwc.write("\
void reg_reset()\n\
{\n")
# 读取定义文件
fpr = open(obj_path + "\\registers.def", 'r', encoding='utf-8')
# 指定名字的最大长度
DEF_NAME_LENGTH_MAX = 40
reg_addr = 0
reg_type_name = " "
bit_mask_name = " "
bit_mask_index = 0
nvd_reg_start = -1
nvd_reg_end = -1
for line in fpr.readlines():
    if line.startswith("#"):  # 生成注释
        fpwh.write(line.replace("#", "//"))
    elif line.startswith("\n"):  # 直接换行
        fpwh.write(line)
    elif not line.startswith(" "):  # 开头不能有空格
        name, value, comment = line_split(line)
        if name.startswith("NVD_REG_START"):
            nvd_reg_start = reg_addr
        elif name.startswith("NVD_REG_END"):
            nvd_reg_end = reg_addr + 1
        elif name.startswith("REG"):  # 寄存器地址定义，为了保持格式统一，请最后定义寄存器地址
            name_list = name.split("_")
            new_type_name = name_list[1]
            if not new_type_name.startswith(reg_type_name):  # 新的寄存器组
                if len(reg_type_name) > 0 and reg_addr > 0:
                    str_def = "#define " + reg_type_name + "_REG_END"
                    str_def = def_align(str_def, DEF_NAME_LENGTH_MAX) + str(reg_addr - 1) + comment + "\n"
                    fpwh.write(str_def)
                fpwh.write("//new register group\n")
                if len(new_type_name) > 0:
                    str_def = "#define " + new_type_name + "_REG_START"
                    str_def = def_align(str_def, DEF_NAME_LENGTH_MAX) + str(reg_addr) + comment + "\n"
                    fpwh.write(str_def)
                reg_type_name = new_type_name
            str_def = "#define " + name
            str_def = def_align(str_def, DEF_NAME_LENGTH_MAX) + str(reg_addr) + comment + "\n"
            fpwh.write(str_def)
            if len(value) > 0:  # 有默认值，写入reset函数
                fpwc.write("    reg_table[%d] = " % reg_addr + value + ";" + comment + "\n")
            reg_addr += 1
        else:
            if not name.startswith(bit_mask_name):  # 新的bit mask组
                name_list = name.split("_")
                bit_mask_name = name_list[0]
                bit_mask_index = 0
            str_def = "#define " + name
            str_def = def_align(str_def, DEF_NAME_LENGTH_MAX) + "(uint32_t)(1 << " + str(bit_mask_index) + ")" + comment + "\n"
            fpwh.write(str_def)
            bit_mask_index += 1
str_def = "#define " + reg_type_name + "_REG_END"
str_def = def_align(str_def, DEF_NAME_LENGTH_MAX) + str(reg_addr - 1) + "\n"
fpwh.write(str_def)
fpwh.write("\n")
fpwh.write("#define REG_NUMBER                       %d\n" % reg_addr)
if nvd_reg_end >= 0:
    fpwh.write("#define NVD_REG_START                    %d\n" % nvd_reg_start)
    fpwh.write("#define NVD_REG_END                      %d\n" % nvd_reg_end)
    fpwh.write("#define NVD_REG_NUMBER                   %d\n" % (nvd_reg_end - nvd_reg_start))
fpwh.write("\n")
fpwh.write("extern uint16_t reg_table[REG_NUMBER];\n")
fpwh.write("void reg_reset();\n\n")
fpwh.write("\
inline uint16_t reg16_read(int addr)\n\
{\n\
    return reg_table[addr];\n\
}\n")

fpwh.write("/*\n*/\n")
fpwh.write("\
inline uint32_t reg32_read(int addr)\n\
{\n\
    return ((uint32_t)reg_table[addr + 1] << 16) + (uint32_t)reg_table[addr];\n\
}\n")

fpwh.write("/*\n*/\n")
fpwh.write("\
inline uint64_t reg64_read(int addr)\n\
{\n\
    return ((uint64_t)reg_table[addr + 3] << 48) +\n\
           ((uint64_t)reg_table[addr + 2] << 32) +\n\
           ((uint64_t)reg_table[addr + 1] << 16) +\n\
            (uint64_t)reg_table[addr];\n\
}\n")

fpwh.write("/*\n*/\n")
fpwh.write("\
inline void reg16_write(int addr, uint16_t data)\n\
{\n\
    reg_table[addr] = data;\n\
}\n")

fpwh.write("/*\n*/\n")
fpwh.write("\
inline void reg32_write(int addr, uint32_t data)\n\
{\n\
    reg_table[addr] = data;\n\
    reg_table[addr + 1] = data >> 16;\n\
}\n")

fpwh.write("/*\n*/\n")
fpwh.write("\
inline void reg64_write(int addr, uint64_t data)\n\
{\n\
    reg_table[addr] = data;\n\
    reg_table[addr + 1] = data >> 16;\n\
    reg_table[addr + 2] = data >> 32;\n\
    reg_table[addr + 3] = data >> 48;\n\
}\n")

fpwc.write("}\n")
fpwc.write("/*\n*/\n")


fpr.close()
fpwh.close()
fpwc.close()
exit(0)

